home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 19 / madtrb14.zip / TURBUTIL.PAS < prev    next >
Pascal/Delphi Source File  |  1985-06-22  |  54KB  |  1,664 lines

  1. {***************************************************************************
  2. *                                                                          *
  3. *  Util.Pas                                                                *
  4. *    This source file by Jim Nutt                                          *
  5. *        CIS 76044,1155                                                    *
  6. *        CIS 71076,1434                                                    *
  7. *        FIDO Jim Nutt @ #452                                              *
  8. *                                                                          *
  9. *    First Uploaded to DL1 of the Borland SIG on CIS November 30, 1984     *
  10. *    This revision 05/24/85                                                *
  11. *    When you get this file please notify me at FIDO #452, I am going to   *
  12. *    attempt to track its distribution.  Thank you, Jim Nutt               *
  13. *                                                                          *
  14. *  This Module Comprises the various utility routines used by the other    *
  15. * modules in the program.  Routines included in this module are:           *
  16. *                                                                          *
  17. *         Routine                   Use                                    *
  18. *  *  1   Upper_Left_X      Returns the left x coordinate of active window *
  19. *  *  2   Upper_Left_Y      Returns the upper y coord of active window     *
  20. *  *  3   Lower_Right_X     Returns the right x coord of active window     *
  21. *  *  4   Lower_Right_Y     Returns the lower y coord of active window     *
  22. *  *  5   RvsOn             Turns on Reverse Video                         *
  23. *  *  6   RvsOff            Turns off Reverse Video                        *
  24. *     7   Yes               Prints a prompt, if user inputs 'Y' returns    *
  25. *                           Trues, otherwise returns False                 *
  26. *  *  8   Click             Produces a single click from the PC speaker    *
  27. *  *  9   Alert             Prints a message to the screen and makes noise *
  28. *  * 10   Beep              Makes noise for a specified period of time     *
  29. *    11   Replicate         Duplicates a character a specified no. of times*
  30. *    12   Left              Left justifys a string in a field of spaces    *
  31. *    13   Center            Centers a string in a field of specified width *
  32. *    14   Get_Payment_Amount Calculates a loan payment amount              *
  33. *    15   Write_Neatly      Outputs numbers with commas                    *
  34. *    16   Get_Str           Writes a string to the screen, allows it to be *
  35. *                           edited and returns the terminating character   *
  36. *    17   Get_Num           Does for numbers what Get_Str does for strings *
  37. *  * 18   Frame             Frames a specified portion of the screen       *
  38. *  * 19   UnFrame           Removes the frame from the screen              *
  39. *  * 20   Menu              Displays a menu and gets a user input          *
  40. *  * 21   Clear_Window      Clears the screen within a window              *
  41. *  * 22   Window_Frame      Sets up, frames and titles a screen window     *
  42. *  * 28   Push_Screen       Saves the current screen                       *
  43. *  * 29   Pop_Screen        Restores a saved screen                        *
  44. *    30   Inc               Increments an integer by 1                     *
  45. *    31   Dec               Decrements an integer by 1                     *
  46. *    34   Upper             Convert String to Upper Case                   *
  47. *    35   Lower             Convert String to Lower Case                   *
  48. *    39   Power             Raises a number to a power                     *
  49. *  * 43   Marquee           Display Marquee and put message in it          *
  50. *  * 44   Help              Displays an appropriate help screen            *
  51. *  * 48   GetForm           generalized input routine                      *
  52. *  * 49   Date              gets the date from the system                  *
  53. *  * 50   Time              gets time from system                          *
  54. *  * 51   Push_Window       pushes a small section of the screen           *
  55. *                                                                          *
  56. *  * Indicates that the routine has IBM PC specific sections and would need*
  57. *    to be modified for other computers                                    *
  58. ****************************************************************************}
  59.  
  60. procedure color(fc,bc : byte);
  61.  
  62. begin
  63.   textcolor(fc);
  64.   textbackground(bc);
  65. end;
  66.  
  67. procedure highvideo;
  68.  
  69. begin
  70.   textcolor(white);
  71.   textbackground(back_ground_color);
  72. end;
  73.  
  74. procedure normvideo;
  75.  
  76. begin
  77.   textcolor(white);
  78.   textbackground(back_ground_color);
  79. end;
  80.  
  81. procedure lowvideo;
  82.  
  83. begin
  84.   textcolor(lightgray);
  85.   textbackground(back_ground_color);
  86. end;
  87.  
  88. {****************************************************************************}
  89.  
  90. function upper_left_x : integer;       {* These four routines allow a       *}
  91. {1*}                                   {* routine to adjust its output      *}
  92. begin                                  {* according to what size window it  *}
  93.   upper_left_x := mem[dseg:$4] + 1;    {* is operating in.  They are        *}
  94. end;                                   {* compatible only with Turbo Pascal *}
  95.                                        {* version 3 on an IBM PC or         *}
  96. function upper_left_y : integer;       {* compatible                        *}
  97. {2*}
  98. begin
  99.   upper_left_y := mem[dseg:$5] + 1;
  100. end;
  101.  
  102. var
  103. {3*}
  104.   lower_right_x : byte absolute cseg: $16a;
  105. {4*}
  106.   lower_right_y : byte absolute cseg: $16b;
  107.  
  108. {****************************************************************************}
  109.  
  110. procedure rvson;                       {*  These two routines turn on and   *}
  111. {5*}                                   {*  off Reverse video on the IBM PC  *}
  112. begin                                  {*************************************}
  113.   textcolor(0);
  114.   textbackground(7);
  115. end;
  116.  
  117. procedure rvsoff;
  118. {6*}
  119. begin
  120.   normvideo;
  121. end;
  122.  
  123. {30**************************************************************************}
  124.  
  125. procedure inc(                     {* Increment argument by One             *}
  126.               var i : integer);        {*****************************************}
  127.  
  128. begin
  129.   i := i + 1;
  130. end;
  131.  
  132. {31**************************************************************************}
  133.  
  134. procedure dec(                     {* Decrement argument by One             *}
  135.               var i : integer);        {*****************************************}
  136.  
  137. begin
  138.   i := i - 1;
  139. end;
  140.  
  141. {26**************************************************************************}
  142.  
  143. procedure wait;                       {* Wait for a keypress from the KBD   *}
  144. {**************************************}
  145.  
  146. var 
  147.   anykey : char;
  148.  
  149. begin
  150.   read(kbd,anykey);
  151. end;
  152.  
  153. {****************************************************************************}
  154.  
  155. type                                 {* Just a couple(?) of type declarations*}
  156.   menu_item       = string[40];      {* needed for a number of routines   *}
  157. {*************************************}
  158.   menu_selections = array[1..30] of menu_item;
  159.   long_string     = string[255];
  160.   register        = record
  161.                       ax,bx,cx,dx,bp,si,di,ds,es,flags : integer;
  162.                     end;
  163.   screenloc       = record
  164.                       ch            : char;
  165.                       attrib        : byte;
  166.                     end;
  167.   video           = array[1..25] of array[1..80] of screenloc;
  168.   video_ptr       = ^video_stack;
  169.   vidscr          = array[1..1] of screenloc;
  170.   charset         = set of char;
  171.   video_stack     = record
  172.                       next_screen  : video_ptr;
  173.                       x1,y1,
  174.                       x2,y2        : byte;
  175.                       screen_store : ^vidscr;
  176.                     end;
  177.  
  178. var
  179.   screenbuffer  : video;
  180.   screen_stack  : video_ptr;
  181.   screen        : ^video;
  182.   com           : integer;
  183.   helpcontext   : integer;
  184.   screenfile    : file of video;
  185.  
  186.   const
  187.     valid_set     : charset = [' '..'~'];
  188.     digits        : charset = ['0'..'9'];
  189.     letters       : charset = ['A'..'Z','a'..'z'];
  190.     uppercase     : charset = [' '..'`','{'..'~'];
  191.     lowercase     : charset = [' '..'@','['..'~'];
  192.     numbers       : charset = ['0'..'9','e','E','+','-','.',','];
  193.     allchars      : charset = [' '..'~'];
  194.  
  195. {7***************************************************************************}
  196.  
  197. function yes(prompt : long_string) : boolean;{* This routine prints PROMPT  *}
  198.                                              {* to the screen and waits for *}
  199. var                                          {* the user to type either a   *}
  200.   inchar : char;                             {* 'y' or 'n'.  It is case     *}
  201.                                              {* insensitive.  If a 'y' is   *}
  202. begin                                        {* entered, the function       *}
  203.   write(prompt);                             {* returns TRUE.               *}
  204.   repeat                                     {*******************************}
  205.     read(kbd,inchar);
  206.   until inchar in ['Y','y','N','n'];
  207.   write(inchar);
  208.   yes := inchar in ['Y','y'];
  209. end;
  210.  
  211. {34**************************************************************************}
  212.  
  213. function upper (s : long_string)       {* Convert Strng S to Upper case     *}
  214.                : long_string;          {* Return uppercase string           *}
  215. {*************************************}
  216.  
  217. var
  218.   i : integer;
  219.   lcase : set of char;
  220.  
  221. begin
  222.   lcase := ['a'..'z'];
  223.  
  224.   for i := 1 to length(s) do
  225.     if s[i] in lcase
  226.       then
  227.         s[i] := char(ord(s[i]) - 32);
  228.   upper := s;
  229. end;
  230.  
  231. {35**************************************************************************}
  232.  
  233. function lower (s : long_string)    {* Convert string S to lowercase        *}
  234.                : long_string;       {* Return lowercase string              *}
  235. {****************************************}
  236.  
  237. var
  238.   i : integer;
  239.   ucase : set of char;
  240.  
  241. begin
  242.   ucase := ['A'..'Z'];
  243.  
  244.   for i := 1 to length(s) do
  245.     if s[i] in ucase
  246.       then
  247.         s[i] := char(ord(s[i]) + 32);
  248.   lower := s;
  249. end;
  250.  
  251. {8***************************************************************************}
  252.  
  253. procedure click;                       {* Makes a clicking noise            *
  254. *************************************}
  255.  
  256. var f,n : integer;
  257.  
  258. begin
  259.   sound(2000);
  260.   delay(5);
  261.   nosound;
  262. end;
  263.  
  264. {9***************************************************************************}
  265.  
  266. procedure alert(message : long_string);{* This routine prints MESSAGE to the*}
  267.                                        {* screen and makes an obnoxious     *}
  268. var                                    {* noise for about 1 second          *}
  269.   i : integer;                         {*************************************}
  270.   i1,i2,i3,i4 : integer;
  271.  
  272.  
  273. begin
  274.   write(message);
  275.   for i4 := 1 to 10 do
  276.     begin
  277.       i2 := 250 + i4 * 25;
  278.       for i3 := 1 to 2 do
  279.         begin
  280.           for i1 := 1 to 30 - i3 * 2 do
  281.             begin
  282.               sound(i1 + i2 + i3 * 2);
  283.               delay(2);
  284.             end;
  285.           delay(5);
  286.           i2 := i2 + 30;
  287.         end;
  288.       nosound;
  289.     end;
  290. end;
  291.  
  292. {21**************************************************************************}
  293.  
  294. procedure clear_window;          {* Clear the Active window                 *}
  295. {*******************************************}
  296.  
  297. var
  298.   i : integer;
  299.  
  300. begin
  301.   for i := 1 to lower_right_y - upper_left_y + 1 do
  302.     begin
  303.       gotoxy(1,i);
  304.       clreol;
  305.     end;
  306. end;
  307.  
  308. {10**************************************************************************}
  309.  
  310. procedure beep(n : integer);    {*  This routine sounds a tone of frequency *}
  311.                                 {*  N for approximately 100 ms              *}
  312. begin                           {********************************************}
  313.   sound(n);
  314.   delay(100);
  315.   nosound;
  316. end;
  317.  
  318. {28**************************************************************************}
  319.  
  320. procedure push_screen;                {* This routine stores the current    *}
  321.                                       {* screen into a temporary storage    *}
  322.                                       {* area                               *}
  323.                                       {**************************************}
  324.  
  325. var
  326.   temp   : video_ptr;
  327.   i,j,k  : integer;
  328.  
  329. begin
  330.   if (maxavail < 0) or (maxavail > 4096)
  331.     then
  332.       begin
  333.         if screen = nil
  334.           then
  335.             screen := ptr($b000,0);
  336.         new(temp);
  337.         temp^.x1 := 1;
  338.         temp^.y1 := 1;
  339.         temp^.x2 := 80;
  340.         temp^.y2 := 25;
  341.         getmem(temp^.screen_store,4000);
  342.         temp^.next_screen := screen_stack;
  343.         k := 1;
  344.         for i := 1 to 25 do
  345.           for j := 1 to 80 do
  346.             begin
  347.               temp^.screen_store^[k] := screen^[i][j];
  348.               inc(k);
  349.             end;
  350.         screen_stack := temp;
  351.       end
  352.     else
  353.       begin
  354.         alert('Insufficient Memory - You are being dumped');
  355.         halt;
  356.       end;
  357. end;
  358.  
  359. {29**************************************************************************}
  360.  
  361. procedure pop_screen;                 {* This routine Pops a screen from the*}
  362.                                       {* Screen Stack                       *}
  363.                                       {**************************************}
  364.  
  365. var
  366.   temp   : video_ptr;
  367.   i,j,k  : integer;
  368.  
  369. begin
  370.   if screen = nil
  371.     then
  372.       screen := ptr($b000,0);
  373.  
  374.   k := 1;
  375.   for i := screen_stack^.y1 to screen_stack^.y2 do
  376.     for j := screen_stack^.x1 to screen_stack^.x2 do
  377.       begin
  378.         screen^[i][j] := screen_stack^.screen_store^[k];
  379.         inc(k);
  380.       end;
  381.  
  382.   temp := screen_stack;
  383.   screen_stack := screen_stack^.next_screen;
  384.   freemem(temp^.screen_store,
  385.           ((temp^.x2 - temp^.x1 + 1) * (temp^.y2 - temp^.y1 + 1)) * 2);
  386.   dispose(temp);
  387. end;
  388.  
  389. {43**************************************************************************}
  390.  
  391. procedure marquee                    {* Draws a marquee in center screen    *}
  392.                  (str : long_string);{* Around the input parameter          *}
  393.                                      {***************************************}
  394.  
  395. const
  396.   onchr = #1;
  397.   offchr = #2;
  398.  
  399. var
  400.   i,j,k : integer;
  401.   x,y   : integer;
  402.   astrsk : array[1..4] of record
  403.                             x,y : integer;
  404.                             oldx,oldy : integer;
  405.                             xi,yi     : integer;
  406.            end;
  407.  
  408. begin
  409.   window(1,1,80,25);
  410.   push_screen;
  411.   clrscr;
  412.   x := 40 - length(str) div 2 - 2;
  413.   for i := 10 to 14 do
  414.     begin
  415.       screen^[i][x].ch := onchr;
  416.       screen^[i][x].attrib := 7;
  417.       screen^[i][x + length(str) + 3].ch := onchr;
  418.       screen^[i][x + length(str) + 3].attrib := 7;
  419.     end;
  420.   for i := x to x + length(str) + 3 do
  421.     begin
  422.       screen^[10][i].ch := onchr;
  423.       screen^[14][i].ch := onchr;
  424.       screen^[10][i].attrib := 7;
  425.       screen^[14][i].attrib := 7;
  426.     end;
  427.   gotoxy(x+2,12);
  428.   highvideo;
  429.   write(str);
  430.   lowvideo;
  431.  
  432.   astrsk[1].x := 40;
  433.   astrsk[1].y := 10;
  434.   astrsk[1].xi := 1;
  435.   astrsk[1].yi := 0;
  436.   astrsk[2].x := x;
  437.   astrsk[2].y := 12;
  438.   astrsk[2].xi := 0;
  439.   astrsk[2].yi := -1;
  440.   astrsk[3].x := x + length(str) + 3;
  441.   astrsk[3].y := 12;
  442.   astrsk[3].xi := 0;
  443.   astrsk[3].yi := 1;
  444.   astrsk[4].x := 40;
  445.   astrsk[4].y := 14;
  446.   astrsk[4].xi := -1;
  447.   astrsk[4].yi := 0;
  448.   astrsk[4].oldx := astrsk[1].x;
  449.   astrsk[4].oldy := astrsk[1].y;
  450.   astrsk[3].oldx := astrsk[2].x;
  451.   astrsk[3].oldy := astrsk[2].y;
  452.   astrsk[2].oldx := astrsk[3].x;
  453.   astrsk[2].oldy := astrsk[3].y;
  454.   astrsk[1].oldx := astrsk[4].x;
  455.   astrsk[1].oldy := astrsk[4].y;
  456.   k := 1;
  457.  
  458.   repeat
  459.     if k > 4
  460.       then
  461.         k := 1;
  462.  
  463.     j := astrsk[k].y;
  464.     i := astrsk[k].x;
  465.  
  466.     if screen = ptr($b800,0)
  467.       then
  468.         repeat
  469.         until (port[$3da] and 1) = 1
  470.       else
  471.         repeat
  472.         until (port[$3ba] and 1) = 1;
  473.  
  474.     screen^[j][i].ch := offchr;
  475.     screen^[astrsk[k].oldy][astrsk[k].oldx].ch := onchr;
  476.     screen^[j][i].attrib := 15;
  477.     screen^[astrsk[k].oldy][astrsk[k].oldx].attrib := 7;
  478.  
  479.     astrsk[k].oldx := astrsk[k].x;
  480.     astrsk[k].oldy := astrsk[k].y;
  481.  
  482.     i := i + astrsk[k].xi;
  483.     j := j + astrsk[k].yi;
  484.  
  485.     if i > (x + length(str) + 3)
  486.       then
  487.         begin
  488.           i := i - astrsk[k].xi;
  489.           astrsk[k].xi := 0;
  490.           astrsk[k].yi := 1;
  491.         end;
  492.  
  493.     if j > 14
  494.       then
  495.         begin
  496.           j := j - astrsk[k].yi;
  497.           astrsk[k].yi := 0;
  498.           astrsk[k].xi := -1;
  499.         end;
  500.     if i < x
  501.       then
  502.         begin
  503.           i := i - astrsk[k].xi;
  504.           astrsk[k].xi := 0;
  505.           astrsk[k].yi := -1;
  506.         end;
  507.     if j < 10
  508.       then
  509.         begin
  510.           j := j - astrsk[k].yi;
  511.           astrsk[k].yi := 0;
  512.           astrsk[k].xi := 1;
  513.         end;
  514.  
  515.     astrsk[k].y := j;
  516.     astrsk[k].x := i;
  517.     inc(k);
  518.  
  519.   until keypressed;
  520.   wait;
  521.   pop_screen;
  522. end;
  523.  
  524. {44**************************************************************************}
  525.  
  526. procedure help;                      {* This routine reads a screen from the*}
  527.                                      {* Screen file and displays it         *}
  528. begin                                {***************************************}
  529.   push_screen;
  530. {$I-}
  531.   seek(screenfile,helpcontext);
  532. {$I+}
  533.   if ioresult = 0
  534.     then
  535.       begin
  536. {$I-}
  537.         read(screenfile,screenbuffer);
  538. {$I+}
  539.         screen^ := screenbuffer;
  540.         if ioresult <> 0
  541.           then
  542.             marquee('Sorry, I''m helpless in this situation')
  543.           else
  544.             wait;
  545.       end
  546.     else
  547.       marquee('Sorry, wish I could help you.');
  548.   pop_screen;
  549. end;
  550.  
  551. {11**************************************************************************}
  552.  
  553. function replicate (                          {* Repeat a character         *}
  554.                     count : integer;          {* Number of Repititions      *}
  555.                     ascii : char              {* Character to be repeated   *}
  556.                     )      : long_string;     {* String containing repeated *}
  557.                                               {* character                  *
  558. * This function takes the character in 'Ascii', repeats it 'Count' times   *
  559. * and returns the resulting string as a 'Long_String'                      *
  560. ****************************************************************************}
  561.  
  562. var
  563.   temp : long_string;  {Used to hold the incomplete result}
  564.   i    : byte;         {For Counter}
  565.  
  566. begin
  567.   temp := '';
  568.   for i := 1 to count do
  569.     temp := temp + ascii;
  570.   replicate := temp;
  571. end; {Replicate}
  572.  
  573. {12*************************************************************************}
  574.  
  575. function left (                       {* Left Justifies a string in a      *}
  576.                str : long_string;    {* field of spaces                   *}
  577.                width : integer       {*************************************}
  578. ) : long_string;
  579.  
  580. begin
  581.   if length(str) > width
  582.     then
  583.       left := copy(str,1,width)
  584.     else
  585.       left := str + replicate(width - length(str),' ');
  586. end;
  587.  
  588. {13**************************************************************************}
  589.  
  590. function center (                              {* Centers a string in field *}
  591.                  field_width   : byte;        {* Width of field for center *}
  592.                  center_string : long_string  {* String to Center          *}
  593. )               : long_string; {* Return the string         *}
  594. {************************************************                           *
  595. * This functions takes the string 'Center_String' and centers it in a      *
  596. * field 'Field_Width' Spaces long.  It returns a 'Long_String' with a      *
  597. * length equal to 'Field_Width'.  If the 'Center_String' is longer than    *
  598. * field width, it is truncated on the right end and is not centered.       *
  599. ****************************************************************************}
  600.  
  601. var 
  602.   temp   : long_string;
  603.   middle : byte;
  604.   num_ldg_blanks : byte;
  605.  
  606. begin
  607.   middle := field_width div 2;
  608.   num_ldg_blanks := middle - (length(center_string) div 2) - 1;
  609.   if length(center_string) > field_width
  610.     then
  611.       center := copy(center_string,1,field_width) {Truncate and return}
  612.     else
  613.       begin
  614.         temp := replicate(num_ldg_blanks,' ') +
  615.                 center_string +
  616.                 replicate(field_width - (num_ldg_blanks+length(center_string)),' ');
  617.         center := copy(temp, 1, field_width)  {Truncate to Field_Width Characters}
  618.       end {Else}
  619. end; {Center}
  620.  
  621. {39*************************************************************************}
  622.  
  623. function power(x : real; y : integer):   {* This function raises X to the  *}
  624.                                        real;
  625. {* Yth power                      *}
  626. {**********************************}
  627.  
  628. var 
  629.   i : integer;
  630.   n : real;
  631.  
  632. begin
  633.   n := 1.0;
  634.   for i := 1 to y do
  635.     n := n * x;
  636.   power := n;
  637. end; {Power}
  638.  
  639. {14*************************************************************************}
  640.  
  641. function  get_payment_amount (loan_amount :   real;
  642.                               interest_rate : real;
  643.                               amort_over    : real
  644. )              : real;
  645.  
  646. var 
  647.  
  648.   monthly_interest_rate   :  real;
  649.   number_of_payments      :  integer;
  650.  
  651. begin
  652.  
  653.   monthly_interest_rate  :=  (interest_rate / 100.0) / 12.0;
  654.   number_of_payments  := trunc (amort_over * 12);
  655.   get_payment_amount := loan_amount *
  656.                         (1 / ((1 - 1 / power((1 + monthly_interest_rate),
  657.                         number_of_payments))/
  658.                         monthly_interest_rate));
  659.  
  660. end;
  661.  
  662. {15**************************************************************************}
  663.  
  664. procedure write_neatly (                 {* Routine to write numbers        *}
  665.                         var outfile  : text;  {* output file                     *}
  666.                         number   : real;  {* Number to be written            *}
  667.                         width    : byte;  {* Width of write area             *}
  668.                         max_dec  : byte   {* Number of decimal places        *}
  669. );                {* This routine takes NUMBER, and  *}
  670. {* formats it with commas and      *}
  671. {* truncates to MAX_DEC decimal    *}
  672. {* places.  If NUMBER is to big to *}
  673. {* fit in WIDTH, then a row of     *}
  674. {* asterisks WIDTH long is output  *}
  675. {***********************************}
  676.  
  677. const 
  678.   valid_digits : set of char = ['0'..'9','.','-','+','e'];
  679.  
  680. var 
  681.   field : long_string;
  682.   point : integer;
  683.   i,j   : integer;       {Spares for counters}
  684.  
  685. begin
  686.   for i := 1 to max_dec do
  687.     number := number * 10;
  688.   number := number + 0.6;
  689.   for i := 1 to max_dec do
  690.     number := number / 10;
  691.   str(number:0:20,field);  {Convert the input to a string}
  692.   i := 1;
  693.  
  694.   i := pos('.',field);  {Where's the Decimal!}
  695.  
  696.   if i = 0
  697.     then
  698.       begin
  699.         field := field + '.';     {If no decimal, then add one}
  700.         point := length(field);
  701.       end
  702.     else
  703.       point := i;
  704.  
  705.   i := point - 3;  {Get the Point?}
  706.  
  707.   while i > 1 do             {put in commas, start at the back and work }
  708.     begin                    {to the front}
  709.       insert(',',field,i);
  710.       i := i - 3
  711.     end;
  712.  
  713.   i := pos('.',field) - 1;    {Find that pesky decimal}
  714.   j := 0;
  715.  
  716.   while j <= max_dec do
  717.     begin
  718.       i := i + 1;                  {Pad to Max_Dec with zeros}
  719.       if i >= length(field)
  720.         then
  721.           field := field + '0';
  722.       j := j + 1;
  723.     end;
  724.  
  725.   field := copy(field,1,i);      {Clean it up a little and elimate trailers}
  726.  
  727.   if max_dec = 0
  728.     then
  729.       field := copy(field,1,i - 1); {Truncate to integer if necessary}
  730.  
  731.   if (length(field) > width) and (width > 0)
  732.     then
  733.       write(replicate(width,'*'))  {Too Big! tell with asterisks}
  734.     else
  735.       write(outfile,field:width);  {all that for this}
  736.  
  737. end;
  738.  
  739. {16**************************************************************************}
  740.  
  741. function get_str (                          {* Get a string with editing    *}
  742.                   var in_str      : long_string; {* String to be edited          *}
  743.                   buffer_len  : integer;     {* Its length                   *}
  744.                   start_x     : integer;     {* Column to start in           *}
  745.                   y           : integer;     {* Row for input                *}
  746.                   force_case  : boolean      {* Force Input to Upper case    *}
  747. )           : char;        {* Return terminating Character *}
  748. {*                              *}
  749. {* This is a fairly versatile   *}
  750. {* string input and editing     *}
  751. {* routine.  It takes IN_STRING *}
  752. {* displays it at START_X,ROW   *}
  753. {* allows the user to edit the  *}
  754. {* string using WordStar(tm)    *}
  755. {* commands.  It returns the    *}
  756. {* character used to terminate  *}
  757. {* input.  By setting FORCE_CASE*}
  758. {* true, all input is forced to *}
  759. {* upper case                   *}
  760. {********************************}
  761.  
  762. const 
  763.   keyclick = true;
  764.  
  765. var 
  766.   insert_mode  : boolean;
  767.   done         : boolean;
  768.   current_char : char;
  769.   x            : byte;
  770.   escape       : boolean;
  771.   current      : char;
  772.   in_string    : long_string;
  773.  
  774. begin
  775.   done         := false;        { **                              }
  776.   insert_mode  := false;        {  * Initialize starting variables}
  777.   gotoxy(start_x,y);            {  *                              }
  778.   x := start_x;                 { **                              }
  779.   write(replicate(buffer_len,'_'));
  780.   in_string := in_str;
  781.   gotoxy(x,y);
  782.   write (in_string);            {Write the initial value of the string}
  783.   gotoxy(x,y);
  784.  
  785.   repeat                                 {Start main edit/input loop}
  786.  
  787.     if (x - start_x) = buffer_len
  788.       then
  789.         current_char := ^m                {Terminate input if buffer is full}
  790.       else
  791.         read(kbd,current_char);           {Get a character}
  792.  
  793.     if (current_char = ^[) and not keypressed
  794.       then
  795.         begin
  796.           in_str := in_string;
  797.           get_str := ^[;
  798.           exit;
  799.         end;
  800.  
  801.     if force_case
  802.       then
  803.         current_char := upcase(current_char); {force case if necessary}
  804.  
  805.     repeat
  806.       escape := false;
  807.       case current_char of        {Act on the current input}
  808.  
  809.         ^[        : if keypressed
  810.                       then
  811.                         begin
  812.                           read(kbd,current_char);
  813.                           escape := true;
  814.                           case current_char of           {Translate escape codes to}
  815.                             'H' : current_char := ^e;    {WordStar command codes   }
  816.                             'P' : current_char := ^x;
  817.                             'K' : current_char := ^s;
  818.                             'M' : current_char := ^d;
  819.                             'S' : current_char := ^g;
  820.                             'R' : current_char := ^v;
  821.                             '<' : current_char := ^r;
  822.                             's' : current_char := ^a;
  823.                             't' : current_char := ^f;
  824.                             ';' : begin
  825.                                     help;
  826.                                     current_char := ^@;
  827.                                   end;
  828.                             'D' : begin                  {Special Terminator}
  829.                                     done := true;
  830.                                     escape := false;
  831.                                   end;
  832.                             'I' : begin
  833.                                     done := true;
  834.                                     escape := false;
  835.                                   end;
  836.                             'Q' : begin
  837.                                     done := true;
  838.                                     escape := false;
  839.                                   end;
  840.                             'O' : begin
  841.                                     done := true;
  842.                                     escape := false;
  843.                                   end;
  844.                             'G' : begin
  845.                                     done := true;
  846.                                     escape := false;
  847.                                   end;
  848.                           end; {Case}
  849.                         end; {^[}
  850.         ^e        : done := true;                  {**               }
  851. { ** All finished }
  852.         ^x        : done := true;                  {**               }
  853.         ^f        : x := start_x + length(in_string);
  854.         ^a        : x := start_x;
  855.         ^r        : begin
  856.                       in_string := in_str;
  857.                       gotoxy(start_x,y);
  858.                       write(replicate(buffer_len,'_'));
  859.                       gotoxy(start_x,y);
  860.                       write(in_string);
  861.                     end;
  862.  
  863.         ^v        : insert_mode := insert_mode xor true; {toggle insert}
  864.  
  865.         ^s        : if x > start_x
  866.                       then    {non destructive backspace}
  867.                         x := x - 1;
  868.  
  869.         ^h,#127   : if x > start_x
  870.                       then    {destructive backspace}
  871.                         begin
  872.                           delete(in_string, x - start_x, 1);
  873.                           gotoxy(start_x,y);
  874.                           write(in_string + '_');
  875.                           x := x - 1;
  876.                         end;
  877.  
  878.         ^d        : if (x - start_x) < buffer_len
  879.                       then  {forward 1 character}
  880.                         if (x - start_x) < length(in_string)
  881.                           then
  882.                             x := x + 1;
  883.  
  884.         ^g        : begin
  885.                       delete(in_string, x - start_x + 1,1); {delete character}
  886.                       gotoxy(start_x,y);                    {under the cursor}
  887.                       write(in_string + '_');
  888.                     end;
  889.  
  890.         ^m        : done := true;         {**}
  891. { *** All Done}
  892.         ^j        : done := true;         {**}
  893.  
  894.         ' '..'~'  : if current_char in valid_set
  895.                       then
  896.                         if (x - start_x) >= length(in_string)
  897.                           then
  898.                             begin
  899.                               in_string := in_string + current_char;
  900.                               gotoxy(x,y);
  901.                               write(current_char);
  902.                               if (x - start_x) < buffer_len
  903.                                 then
  904.                                   x := x + 1;
  905.                             end
  906.  
  907.                           else
  908.  
  909.                             if insert_mode
  910.                               then   {Just a run of the mill character}
  911.                                 begin               {Insert Mode}
  912.                                   insert(current_char,in_string, x - start_x + 1);
  913.                                   in_string := copy(in_string,1,buffer_len);
  914.                                   gotoxy(start_x,y);
  915.                                   write(in_string);
  916.  
  917.                                   if (x - start_x) < buffer_len
  918.                                     then
  919.                                       x := x + 1;
  920.                                   gotoxy(x,y);
  921.                                 end
  922.  
  923.                               else
  924.  
  925.                                 begin              {OverWrite Mode}
  926.                                   in_string[x - start_x + 1] := current_char;
  927.                                   gotoxy(x,y);
  928.                                   write(current_char);
  929.                                   if (x - start_x) < buffer_len
  930.                                     then
  931.                                       x := x + 1;
  932.                                 end
  933.                       else
  934.                         beep(1720)
  935.       end; {Case}
  936.     until not escape;
  937.     gotoxy(x,y);
  938.     if keyclick
  939.       then
  940.         click;
  941.   until done;
  942.   get_str := current_char;               {Return the terminator}
  943.   in_str := in_string;
  944. end;
  945.  
  946. {17**************************************************************************}
  947.  
  948. function get_num  (                   {* This routine gets number from user *}
  949.                    var value     : real;   {* Current Value and Returned Value   *}
  950.                    decimals  : integer;{* Number of Decimal Places           *}
  951.                    min_value : real;   {* Minimum Value                      *}
  952.                    max_value : real;   {* Maximum Value                      *}
  953.                    x         : byte;   {* Column                             *}
  954.                    y         : byte    {* Row                                *}
  955. )         : char;   {* Terminator                         *}
  956. {*                                    *}
  957. {* This routine does basically the    *}
  958. {* thing as Get_Str only for numbers  *}
  959. {* There are more options however.    *}
  960. {* Basically Min and Max Value allow  *}
  961. {* to specify the range of acceptable *}
  962. {* values and DECIMALS allows you to  *}
  963. {* specify the number of decimal      *}
  964. {* places desired                     *}
  965. {**************************************}
  966.  
  967. var 
  968.   i1,i2  : integer;
  969.   s1     : long_string;
  970.   s2     : long_string;
  971.   s3     : long_string;
  972.   inchar : char;
  973.  
  974. begin
  975.   str(value:1:decimals,s1);       {Convert to a string}
  976.   str(max_value:1:decimals,s3);   {find out how long a string max val is}
  977.  
  978.   repeat                 {Main Loop}
  979.     s2 := '';
  980.  
  981.     valid_set := numbers;
  982.     inchar := get_str(s1,length(s3),x,y,false); {Get_Str does the }
  983. {work}
  984.     for i2 := 1 to length(s1) do     {Strip out non digits}
  985.       if s1[i2] in (numbers - [','])
  986.         then
  987.           s2 := s2 + s1[i2];
  988.  
  989.     val(s2,value,i1);                 {Find out its value}
  990.  
  991.   until (value >= min_value) and (value <= max_value) and (i1 = 0); {do it }
  992. {until its right}
  993.  
  994.   gotoxy(x,y);
  995.  
  996.   write_neatly(output,value,length(s3),decimals); {print the result}
  997.   valid_set := allchars;
  998.  
  999.   get_num := inchar;  {Assign the terminator}
  1000.  
  1001. end;
  1002.  
  1003. {18**************************************************************************}
  1004.  
  1005. procedure frame(                      {* Frame the section of screen within *}
  1006.                 upperleftx,           {* these bounds                       *}
  1007.                 upperlefty,           {**************************************}
  1008.                 lowerrightx,
  1009.                 lowerrighty: integer);
  1010.  
  1011. var 
  1012.   i: integer;
  1013.  
  1014. begin
  1015.   gotoxy(upperleftx,upperlefty);
  1016.   write(chr(218));
  1017.   gotoxy(upperleftx,lowerrighty);
  1018.   write(chr(192));
  1019.   gotoxy(lowerrightx,upperlefty);
  1020.   write(chr(191));
  1021.   gotoxy(lowerrightx,lowerrighty);
  1022.   write(chr(217));
  1023.   for i := upperleftx + 1 to lowerrightx - 1 do
  1024.     begin
  1025.       gotoxy(i,upperlefty);
  1026.       write(chr(196));
  1027.       gotoxy(i,lowerrighty);
  1028.       write(chr(196));
  1029.     end;
  1030.   for i := upperlefty + 1 to lowerrighty - 1 do
  1031.     begin
  1032.       gotoxy(upperleftx,i);
  1033.       write(chr(179));
  1034.       gotoxy(lowerrightx,i);
  1035.       write(chr(179));
  1036.     end;
  1037. end;  { Frame }
  1038.  
  1039. {19***************************************************************************}
  1040.  
  1041. procedure unframe(                      {* This routine does the opposite of *}
  1042.                   upperleftx,           {* frame                             *}
  1043.                   upperlefty,           {*************************************}
  1044.                   lowerrightx,
  1045.                   lowerrighty: integer);
  1046.  
  1047. var 
  1048.   i: integer;
  1049. begin
  1050.   gotoxy(upperleftx, upperlefty);
  1051.   write(' ');
  1052.  
  1053.   for i:=upperleftx+1 to lowerrightx-1 do
  1054.     write(' ');
  1055.  
  1056.   write(' ');
  1057.  
  1058.   for i:=upperlefty+1 to lowerrighty-1 do
  1059.     begin
  1060.       gotoxy(upperleftx , i);
  1061.       write(' ');
  1062.       gotoxy(lowerrightx, i);
  1063.       write(' ');
  1064.     end;
  1065.  
  1066.   gotoxy(upperleftx, lowerrighty);
  1067.   write(' ');
  1068.  
  1069.   for i:=upperleftx+1 to lowerrightx-1 do
  1070.     write(' ');
  1071.  
  1072.   write(' ');
  1073. end;  {UnFrame }
  1074.  
  1075. {20**************************************************************************}
  1076.  
  1077. function menu (                               {* Display a Menu             *}
  1078.                item_list  : menu_selections; {* List of Options on Menu    *}
  1079. {* Last Item must be Null     *}
  1080. {* String for proper operation*}
  1081. {* No more than 30 items per  *}
  1082.                menu_x     : integer;         {* X Location of Menu         *}
  1083.                menu_y     : integer;         {* Y Location of Menu         *}
  1084.                menu_title : menu_item;       {* Title of Menu              *}
  1085.                title_x    : integer;         {* X Location of Title        *}
  1086.                title_y    : integer;         {* Y Location of Title        *}
  1087.                default    : integer          {* Default Selection          *}
  1088. )            : integer;         {* Return the index of the    *}
  1089. {* item selected by the user  *}
  1090. {*                            *}
  1091. {***********************************************                            *
  1092. * This Routine Displays a Menu on the screen at the location specified by   *
  1093. * Menu_X and Menu_Y.  The Menu Title is displayed in Reverse Video at the   *
  1094. * Location specified by Title_X and Title_Y.  The User selects an item from *
  1095. * the menu by using <CTRL>-E to move a reverse video cursor bar up and      *
  1096. * <CTRL>-X to move it down.  After the cursor is on the item desired by the *
  1097. * user, he must press return.  At this point the routine returns the item   *
  1098. * number of the selection.                                                  *
  1099. *****************************************************************************}
  1100.  
  1101. const 
  1102.   cr = #13;
  1103.   up = #5;
  1104.   dn = #24;
  1105.  
  1106. var 
  1107.   first_shown : integer;
  1108.   last_shown  : integer;
  1109.   inchar : char;
  1110.   menu_pointer : 1..15;
  1111.   menu_length : 1..15;
  1112.   last : integer;
  1113.   last_y : integer;
  1114.   width : integer;
  1115.   len   : integer;
  1116.   maxlen : integer;
  1117.   x1,x2,y1,y2 : integer;
  1118.   i,j,k   : integer;
  1119.   instr : long_string;
  1120.   ls    : integer;
  1121.  
  1122. begin {Menu}
  1123.  
  1124.   instr := '';
  1125.  
  1126.   width := lower_right_x - upper_left_x + 1;   {Calculate Window Size}
  1127.   len   := lower_right_y - upper_left_y + 1;
  1128.   maxlen  := len + 2;
  1129.  
  1130.   if width > 70
  1131.     then begin
  1132.            gotoxy(1,1);
  1133.            color(12,back_ground_color);
  1134.            writeln('IMEX -  (800) 222 - 9188');
  1135.            color(15,back_ground_color2);
  1136.            write(center(width,menu_title));
  1137.       end
  1138.     else begin
  1139.            gotoxy(title_x,title_y);
  1140.            color(15,back_ground_color2);
  1141.            write(menu_title);
  1142.       end;
  1143.  
  1144.   color(15,back_ground_color);
  1145.  
  1146.   if width > 38
  1147.     then        {If there is enough room, write out instructions}
  1148.       begin                   {otherwise, they is out a luck}
  1149.         maxlen := maxlen - 3;
  1150.         frame(1,len-3,width-1,len);
  1151.         gotoxy((width div 2) - 6,len-3);
  1152.         write(#17);
  1153.         rvson;
  1154.         write('Instructions');
  1155.         rvsoff;
  1156.         write(#16);
  1157.         textcolor(15);
  1158.         gotoxy(2,len-2);
  1159.         write(center(width-3,'Use '+#24+' and '+#25+' to Highlight a Selection'));
  1160.         gotoxy(2,len-1);
  1161.         write(center(width-3,' And '+#17+'─┘ to make the Selection'));
  1162.       end;
  1163.  
  1164.   inchar := ' ';               {Initialize variables}
  1165.   menu_pointer := 1;
  1166.  
  1167. {Display the actual menu selections and determine how many selections
  1168. are available}
  1169.  
  1170.   maxlen := maxlen - menu_y;
  1171.  
  1172.   menu_length := 1;
  1173.   while (item_list[menu_length + 1] <> '*') and
  1174.         (item_list[menu_length + 1] <> '' ) do
  1175.     menu_length := menu_length + 1;
  1176.  
  1177.   for i := 1 to menu_length do
  1178.     if length(item_list[i]) > 40
  1179.       then
  1180.         item_list[i] := copy(item_list[i],1,40);
  1181.  
  1182.   if maxlen > ((menu_length) * 2)
  1183.     then
  1184.       ls := 2
  1185.     else
  1186.       ls := 1;
  1187.  
  1188.   first_shown := 1;
  1189.   last_shown := menu_length;
  1190.   while (last_shown * ls + menu_y) > maxlen do
  1191.     last_shown := last_shown - 1;
  1192.  
  1193.   menu_pointer := default;
  1194.   if menu_pointer > menu_length
  1195.     then
  1196.       menu_pointer := last_shown;
  1197.  
  1198.   i := 0;
  1199.   for j := first_shown to last_shown do
  1200.     begin
  1201.       gotoxy(menu_x, menu_y + (i * ls));
  1202.       write(item_list[j]:length(item_list[j]));
  1203.       i := i + 1;
  1204.       clreol;
  1205.     end;
  1206.  
  1207.   last_y := wherey;
  1208.   last := first_shown;
  1209.   if last = default
  1210.     then
  1211.       last := last_shown;
  1212.  
  1213.   while inchar <> cr do          {Main loop}
  1214.  
  1215.     begin
  1216.  
  1217.       if (menu_pointer < first_shown) or (menu_pointer > last_shown)
  1218.         then
  1219.           begin
  1220.             while  menu_pointer < first_shown do
  1221.               begin
  1222.                 first_shown := first_shown - 1;
  1223.                 if first_shown < 1
  1224.                   then
  1225.                     first_shown := 1;
  1226.                 last_shown := last_shown - 1;
  1227.                 if last_shown < 1
  1228.                   then
  1229.                     last_shown := 1;
  1230.               end;
  1231.  
  1232.             while menu_pointer > last_shown do
  1233.               begin
  1234.                 first_shown := first_shown + 1;
  1235.                 last_shown := last_shown + 1;
  1236.               end;
  1237.  
  1238.             if last_shown > menu_length
  1239.               then
  1240.                 last_shown := menu_length;
  1241.  
  1242.             i := 0;
  1243.             for j := first_shown to last_shown do
  1244.               begin
  1245.                 if j = menu_pointer
  1246.                   then
  1247.                     rvson;
  1248.                 gotoxy(menu_x, menu_y + (i * ls));
  1249.                 write(item_list[j]:length(item_list[j]));
  1250.                 if (item_list[j][length(item_list[j])] = ']') and (menu_pointer = j)
  1251.                   then
  1252.                     begin
  1253.                       write(^h,^h,'X]');
  1254.                       last_y := wherey;
  1255.                     end;
  1256.                 i := i + 1;
  1257.                 if j = menu_pointer
  1258.                   then
  1259.                     rvsoff;
  1260.                 clreol;
  1261.               end;
  1262.           end
  1263.         else
  1264.           begin
  1265.             rvsoff;
  1266.             if last = (menu_length)
  1267.               then
  1268.                 last_y := (last_shown - first_shown) * ls + menu_y;
  1269.             if last = 1
  1270.               then
  1271.                 last_y := menu_y;
  1272.             gotoxy(menu_x,last_y);
  1273.             write(item_list[last]);
  1274.             gotoxy(menu_x,menu_y + (menu_pointer - first_shown) * ls);
  1275.             rvson;
  1276.             last_y := wherey;
  1277.             write(item_list[menu_pointer]:length(item_list[menu_pointer]));
  1278.             if item_list[menu_pointer][length(item_list[menu_pointer])] = ']'
  1279.               then
  1280.                 write(^h,^h,'X]');
  1281.             rvsoff;
  1282.             clreol;
  1283.           end;
  1284.  
  1285.       read(kbd,inchar);    {get a character from the user}
  1286.       click;
  1287.       if (inchar = ^[) and not keypressed
  1288.         then
  1289.           begin
  1290.             menu := default;
  1291.             exit;
  1292.           end;
  1293.  
  1294.       last := menu_pointer;
  1295.  
  1296.       if not (inchar in [^[,up,dn,cr])
  1297.         then
  1298.  
  1299.           begin
  1300.  
  1301.             if inchar = #127
  1302.               then
  1303.                 instr := ''
  1304.               else
  1305.  
  1306.                 if inchar = ^h
  1307.                   then
  1308.                     delete(instr,length(instr),1)
  1309.                   else
  1310.                     instr := instr + inchar;
  1311.  
  1312.             j := 0;
  1313.             k := 0;
  1314.  
  1315.             for i := 1 to menu_length do
  1316.  
  1317.               if lower(instr) = lower(copy(item_list[i],1,length(instr)))
  1318.                 then
  1319.  
  1320.                   begin
  1321.                     inc(j);
  1322.  
  1323.                     if k = 0
  1324.                       then
  1325.                         k := i;
  1326.  
  1327.                   end;
  1328.  
  1329.             if k <> 0
  1330.               then
  1331.                 menu_pointer := k;
  1332.  
  1333.             if (j = 1) or (j = 0)
  1334.               then
  1335.                 instr := '';
  1336.  
  1337.           end;
  1338.  
  1339.       if (inchar = ^[) and keypressed
  1340.         then   {get the escape code}
  1341.           read(kbd, inchar);
  1342.  
  1343.       if inchar = ';'
  1344.         then
  1345.           begin
  1346.             x1 := upper_left_x;
  1347.             y1 := upper_left_y;
  1348.             x2 := lower_right_x;
  1349.             y2 := lower_right_y;
  1350.             help;
  1351.             window(x1,y1,x2,y2);
  1352.           end;
  1353.  
  1354.       if (inchar = up) or (inchar = 'H')
  1355.         then
  1356.           begin                                    {They hit up arrow}
  1357.             menu_pointer := menu_pointer - 1;
  1358.             if menu_pointer < 1
  1359.               then
  1360.                 menu_pointer := (menu_length);
  1361.             instr := '';
  1362.           end;  {If}
  1363.  
  1364.       if (inchar = dn) or (inchar = 'P')
  1365.         then
  1366.           begin                                    {They hit down arrow}
  1367.             menu_pointer := menu_pointer + 1;
  1368.             if menu_pointer > menu_length
  1369.               then
  1370.                 menu_pointer := 1;
  1371.             instr := '';
  1372.           end;  {If}
  1373.  
  1374.     end; {While}
  1375.  
  1376.   beep(440);                                {They made a selection, beep once}
  1377.   menu := menu_pointer;                     {to confirm}
  1378.  
  1379. end; {Menu}
  1380.  
  1381. {22**************************************************************************}
  1382.  
  1383. procedure window_frame(x1,y1,             {* Create, frame and title a      *}
  1384.                        x2,y2 : integer;   {* window                         *}
  1385.                        title : menu_item);{**********************************}
  1386.  
  1387. var 
  1388.   center : integer;
  1389.  
  1390. begin
  1391.   window(1,1,80,25);
  1392.   frame(x1 - 1, y1 - 1,
  1393.         x2 + 1, y2 + 1);
  1394.   center := ((x2 - x1) div 2) + x1;
  1395.   gotoxy(center - (length(title) div 2)-1,y1-1);
  1396.   write(#17);
  1397.   rvson;
  1398.   write(title);
  1399.   rvsoff;
  1400.   write(#16);
  1401.   window(x1,y1,x2,y2);
  1402.   clear_window;
  1403. end;
  1404.  
  1405. {48**************************************************************************}
  1406.  
  1407. type 
  1408.   typelist = (ustr,lstr,ulstr,rnum,inum,yn,dte,phne,tme);
  1409. {ustr               upper case string
  1410. lstr               lower case string
  1411. ulstr              upper lower case string
  1412. rnum               real number
  1413. inum               integer
  1414. yn                 yes/no reply
  1415. dte                date
  1416. phne               phone number
  1417. tme                time}
  1418.  
  1419. function getform(   var value;
  1420.                  vtype   : typelist;
  1421.                  x,y,
  1422.                  dp,len  : integer;
  1423.                  lstrg   : long_string;
  1424.                  lx,ly   : integer
  1425. ) : char;
  1426.  
  1427. var 
  1428.   realval : real absolute value;
  1429.   intval  : integer absolute value;
  1430.   strval  : long_string absolute value;
  1431.   boolval : boolean absolute value;
  1432.   mval    : real;
  1433.   tint    : integer;
  1434.   tstr1,
  1435.   tstr    : long_string;
  1436.   valid   : boolean;
  1437.   tchar   : char;
  1438.  
  1439. begin
  1440.   gotoxy(lx,ly);
  1441.   highvideo;
  1442.   write(lstrg);
  1443.   case vtype of
  1444.  
  1445.     ustr  : begin
  1446.               getform := get_str(strval,len,x,y,true);
  1447.               valid_set := allchars;
  1448.             end;
  1449.     lstr  : begin
  1450.               valid_set := lowercase;
  1451.               getform := get_str(strval,len,x,y,false);
  1452.               strval := lower(strval);
  1453.               valid_set := allchars;
  1454.             end;
  1455.     ulstr : getform := get_str(strval,len,x,y,false);
  1456.     rnum  : begin
  1457.               valid_set := numbers;
  1458.               val(replicate(len - dp - 1,'9'),mval,tint);
  1459.               getform := get_num(realval,dp,0,mval,x,y);
  1460.               valid_set := allchars;
  1461.             end;
  1462.     inum  : begin
  1463.               valid_set := numbers;
  1464.               getform := get_num(mval,0,-32767,maxint,x,y);
  1465.               intval := trunc(mval);
  1466.               valid_set := allchars;
  1467.             end;
  1468.     yn    : begin
  1469.               valid_set := ['Y','N','y','n'];
  1470.               gotoxy(x,y);
  1471.               if boolval
  1472.                 then
  1473.                   tstr := 'Y'
  1474.                 else
  1475.                   tstr := 'N';
  1476.               repeat
  1477.                 tchar := get_str(tstr,1,x,y,true);
  1478.               until tstr[1] in ['Y','N'];
  1479.               boolval := tstr = 'Y';
  1480.               getform := tchar;
  1481.               valid_set := allchars;
  1482.             end;
  1483.     dte   : begin
  1484.               valid := false;
  1485.               valid_set := digits;
  1486.               tstr := copy(strval,1,2);
  1487.               repeat
  1488.                 getform := get_str(tstr,2,x,y,false);
  1489.                 valid := ((tstr[1] = '1') and (tstr[2] in ['0'..'2'])) or
  1490.                          ((tstr[1] in [' ','0']) and (tstr[2] in ['0'..'9']));
  1491.               until valid;
  1492.               tstr1 := tstr + '/';
  1493.               gotoxy(x+2,y);
  1494.               write('/');
  1495.               valid := false;
  1496.               tstr := copy(strval,4,2);
  1497.               repeat
  1498.                 getform := get_str(tstr,2,x+3,y,false);
  1499.                 valid := ((tstr[1] = '3') and (tstr[2] in ['0'..'1'])) or
  1500.                          ((tstr[1] in [' ','0'..'2']) and (tstr[2] in ['0'..'9']));
  1501.               until valid;
  1502.               tstr1 := tstr1 + tstr + '/';
  1503.               gotoxy(x+5,y);
  1504.               write('/');
  1505.               valid := false;
  1506.               tstr := copy(strval,7,2);
  1507.               repeat
  1508.                 getform := get_str(tstr,2,x+6,y,false);
  1509.                 valid := (tstr[1] in ['8','9']) and (tstr[2] in ['0'..'9']);
  1510.               until valid;
  1511.               strval := tstr1 + tstr;
  1512.               valid_set := allchars;
  1513.             end;
  1514.     tme   : begin
  1515.               valid_set := digits;
  1516.               valid := false;
  1517.               tstr := copy(strval,1,2);
  1518.               repeat
  1519.                 getform := get_str(tstr,2,x,y,false);
  1520.                 valid := ((tstr[1] = '1') and (tstr[2] in ['0'..'2'])) or
  1521.                          ((tstr[1] in [' ','0']) and (tstr[2] in ['0'..'9']));
  1522.               until valid;
  1523.               tstr1 := tstr + ':';
  1524.               gotoxy(x+2,y);
  1525.               write('/');
  1526.               valid := false;
  1527.               tstr := copy(strval,4,2);
  1528.               repeat
  1529.                 getform := get_str(tstr,2,x+3,y,false);
  1530.                 valid := (tstr[1] in [' ','0'..'5']) and (tstr[2] in ['0'..'9']);
  1531.               until valid;
  1532.               tstr1 := tstr1 + tstr + ':';
  1533.               gotoxy(x+5,y);
  1534.               write('/');
  1535.               valid := false;
  1536.               tstr := copy(strval,7,2);
  1537.               repeat
  1538.                 getform := get_str(tstr,2,x+6,y,false);
  1539.                 valid := (tstr[1] in ['0'..'5']) and (tstr[2] in ['0'..'9']);
  1540.               until valid;
  1541.               strval := tstr1 + tstr;
  1542.               valid_set := allchars;
  1543.             end;
  1544.     phne  : begin
  1545.               valid_set := digits;
  1546.               valid := false;
  1547.               gotoxy(x,y);
  1548.               write('(');
  1549.               tstr := copy(strval,2,3);
  1550.               repeat
  1551.                 getform := get_str(tstr,3,x+1,y,false);
  1552.                 valid := tstr[2] in ['0','1'];
  1553.               until valid;
  1554.               tstr1 := '(' + tstr + ') ';
  1555.               gotoxy(x+4,y);
  1556.               write(') ');
  1557.               tstr := copy(strval,7,3);
  1558.               getform := get_str(tstr,3,x+6,y,false);
  1559.               tstr1 := tstr1 + tstr + '-';
  1560.               gotoxy(x+10,y);
  1561.               write('-');
  1562.               tstr := copy(strval,11,4);
  1563.               getform := get_str(tstr,4,x+10,y,false);
  1564.               tstr1 := tstr1 + tstr;
  1565.               strval := tstr1;
  1566.               valid_set := allchars;
  1567.             end;
  1568.   end;
  1569.  
  1570.   gotoxy(lx,ly);
  1571.   lowvideo;
  1572.   write(lstrg);
  1573. end;
  1574.  
  1575. {*********************************************************************}
  1576.  
  1577. const monthmask = $000f;
  1578.   daymask = $001f;
  1579.   minutemask = $003f;
  1580.   secondmask = $001f;
  1581.  
  1582. type  dtstr = string[8];
  1583.  
  1584. {49*******************************************************************}
  1585.  
  1586. function getdate : dtstr;
  1587.  
  1588. var 
  1589.   allregs : register;
  1590.   month, day,
  1591.   year    : string[2];
  1592.   i       : integer;
  1593.   tstr    : dtstr;
  1594.  
  1595. begin
  1596.   allregs.ax := $2a * 256;
  1597.   msdos(allregs);
  1598.   str((allregs.dx div 256): 2,month);
  1599.   str((allregs.dx mod 256): 2,day);
  1600.   str((allregs.cx - 1900): 2,year);
  1601.   tstr := month + '/' + day + '/' + year;
  1602.   for i := 1 to 8 do
  1603.     if tstr[i] = ' '
  1604.       then
  1605.         tstr[i] := '0';
  1606.   getdate := tstr;
  1607. end;  {getdate}
  1608.  
  1609. {50*******************************************************************}
  1610.  
  1611. function gettime : dtstr;
  1612.  
  1613. var 
  1614.   allregs : register;
  1615.   hour, minute,
  1616.   second  : string[2];
  1617.   i       : integer;
  1618.   tstr    : dtstr;
  1619.  
  1620. begin
  1621.   allregs.ax := $2c * 256;
  1622.   msdos(allregs);
  1623.   str((allregs.cx div 256): 2,hour);
  1624.   str((allregs.cx mod 256): 2,minute);
  1625.   str((allregs.dx div 256): 2,second);
  1626.   tstr := hour + ':' + minute + ':' + second;
  1627.   for i := 1 to 8 do
  1628.     if tstr[i] = ' '
  1629.       then
  1630.         tstr[i] := '0';
  1631.   gettime := tstr;
  1632. end;  {gettime}
  1633.  
  1634. {51*******************************************************************}
  1635.  
  1636. procedure push_window(x1,y1,x2,y2 : integer);
  1637.  
  1638. var 
  1639.   temp : video_ptr;
  1640.   i,j,k  : integer;
  1641.  
  1642. begin
  1643.   if screen = nil
  1644.     then
  1645.       screen := ptr($b000,0);
  1646.   new(temp);
  1647.   temp^.x1 := x1;
  1648.   temp^.y1 := y1;
  1649.   temp^.x2 := x2;
  1650.   temp^.y2 := y2;
  1651.   getmem(temp^.screen_store,((x2 - x1 + 1) * (y2 - y1 + 1)) * 2);
  1652.   temp^.next_screen := screen_stack;
  1653.   k := 1;
  1654.   for i := y1 to y2 do
  1655.     for j := x1 to x2 do
  1656.       begin
  1657.         temp^.screen_store^[k] := screen^[i][j];
  1658.         inc(k);
  1659.       end;
  1660.   screen_stack := temp;
  1661. end;
  1662.  
  1663. {*************************}
  1664.